XMLHTTPRequest属性、方法、事件整理大全。
xhr 对象的方法
-
open(method:string, url:string, async?:boolean=true, username?:string, password: string)
- 用于创建
HTTP
请求,但请求并未发送。 -
method
, 请求类型,如GET
、POST
等,大小写不敏感。 -
url
,URL
地址 -
async
, 是否异步,默认true
。
若为同步请求时-
xhr.timeout
值必须为 0。 -
xhr.withCredentials
值必须为 false。 -
xhr.responseType
值必须为""
,(text
也不允许)。
-
-
username
, 用户名,一般不用。 -
password
, 密码,一般不用。
- 用于创建
-
send(body?:Object=null)
-
定义
HTTP
请求的数据(body
),当method
为GET
、HEAD
时,该参数忽略。body
可为ArrayBuffer
、Blob、Document
(类似XML
格式数据)、DOMString
(字符串)、FormData
(表单)。
ArrayBuffer、Blob、Document、DOMString、Formdata 详细参考。
注意:body 参数会影响请求头部的content-type
默认值。- 如果
data
是Document
类型,同时也是HTML Document
类型,则content-type
默认值为text/html;charset=UTF-8
;否则为application/xml
;charset=UTF-8; - 如果
data
是DOMString
类型,content-type
默认值为text/plain;charset=UTF-8
; - 如果
data
是FormData
类型,content-type
默认值为multipart/form-data; boundary=[xxx]
-
如果
data
是其他类型,则不会设置content-type
的默认值如果用 xhr.setRequestHeader()手动设置了中 content-type 的值,以上默认值就会被覆盖。
若在断网状态下调用 xhr.send(data)方法,则会抛错:Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest'。一旦程序抛出错误,如果不 catch 就无法继续执行后面的代码,所以调用 xhr.send(data)方法时,应该用 try-catch 捕捉错误。
try{ xhr.send(data) }catch(e) { //doSomething... };
- 如果
-
-
abort()
- 若请求已发出,则会终止请求,并将 readyState 置为 0.
- 调用后,应将 xhr 对象置为 null 以促进垃圾回收。由于内存原因,不建议重用 xhr 对象。
扩展阅读:和浏览器异步请求取消相关的那些事
-
overrideMimeType(type:string)
重写 response 的 content-type。功能如同 xhr.responseType,已可以摒弃。 -
setRequestHeader(header:string, value:string)
- 设置请求 HTTP 请求头信息。如
content-type
、cookie
、accept-xxx
等。 - header 参数大小写不敏感。
- 必须在
open()
方法后,send()
方法前调用,否则会抛错。 - 可调用多次,最终值不会覆盖,而是采用追加
append
方式。 -
禁止设置以下请求头,否则会抛错。
Accept-Charset
Accept-Encoding
Access-Control-Request-Headers
Access-Control-Request-Method
Connection
Content-Length
Cookie
Cookie2
Date
DNT
Expect
Host
Keep-Alive
Origin
Referer
TE
Trailer
Transfer-Encoding
Upgrade
User-Agent
Via
- 设置请求 HTTP 请求头信息。如
-
getResponseHeader(header:string)
- 获取某个指定 header 字段的值。
- header 字段不区分大小写。
- 有严格安全限制,详见
getAllResponseHeaders
方法。
-
getAllResponseHeaders()
- 获取 response 中所有 header 字段。
-
有严格安全限制。如下:
- 无论跨域或同域请求,无法获取
Set-Cookie
、Set-Cookie2
字段值。 -
跨域请求,只可获取simple response header和Access-Control-Expose-Headers(名词解释见下方),否则会报错:
Refused to get unsafe header
。故若想访问其他字段,需后端添加到Access-Control-Expose-Headers
中。simple response header
包括的header
字段有:Cache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
。
- 无论跨域或同域请求,无法获取
> `Access-Control-Expose-Headers`:跨域请求独有,同域请求无。该字段中列举的 `header` 字段为服务器允许暴露给客户端访问的字段。
> 句法:```Access-Control-Expose-Headers: <header-name>, <header-name>, ...```
xhr 的属性
-
readyState
[只读属性]用于追踪xhr
当前的状态,共有 5 种可能的值,分别对应xhr
不同的阶段。
每次readyState
值变化时,都会触发xhr.onreadystatechange
事件。值 状态 描述 0
UNSENT
(初始状态,未打开)此时 xhr
对象被成功构造,open()
方法还未被调用1
OPENED
(已打开,未发送)open()
方法已被成功调用,send()
方法还未被调用。注意:只有xhr
处于OPENED
状态,才能调用xhr.setRequestHeader()
和xhr.send()
,否则会报错2
HEADERS_RECEIVED
(已获取响应头)send()
方法已经被调用, 响应头和响应状态已经返回3
LOADING
(正在下载响应体)响应体( response entity body
)正在下载中,此状态下xhr.response
可能已经有了响应数据4
DONE
(整个数据传输过程结束)整个数据传输过程结束,不管本次请求是成功还是失败 -
status
和statusText
status
属性表示HTTP
响应状态码,如200
、302
、400
等。statusText
属性表示HTTP
响应状态的描述文本,如OK
、Not Found
等。
注意,在xhr.onload
事件中,不能简单的判断xhr.status === 200
,因为20x
、304
等HTTP
状态码也被认为是请求成功。
参考以下代码:xhr.onload = function () { //如果请求成功 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ //do successCallback } }
-
responseType
和response
可在xhr.send()
前设置responseType
,用于指定返回的响应数据类型。和xhr.overrideMimeType()
方法效果相同,推荐使用responseType
。- IE10/IE11 不支持
xhr.responseType
为json
。 -
部分浏览器不支持
xhr.responseType
为blob
。值 描述 ""
将 responseType
设为空字符串与设置为text
相同, 是默认类型 (实际上是DOMString
)。arraybuffer
response
是一个包含二进制数据的JavaScript ArrayBuffer
。blob
response
是一个包含二进制数据的Blob
对象 。document
response
是一个HTML Document
或XML XMLDocument
,这取决于接收到的数据的MIME
类型。使用XHR
获取HTML
请参阅HTML in XMLHttpRequest
。json
response
是一个JavaScript
对象。这个对象是通过将接收到的数据类型视为JSON
解析得到的。text
response
是包含在DOMString
对象中的文本。moz-chunked-arraybuffer
与 arraybuffer
相似,但是数据会被接收到一个流中。使用此响应类型时,响应中的值仅在progress
事件的处理程序中可用,并且只包含上一次响应progress
事件以后收到的数据,而不是自请求发送以来收到的所有数据。在progress
事件处理时访问response
将返回到目前为止收到的数据。在progress
事件处理程序之外访问,response
的值会始终为null
。ms-stream
response
是下载流的一部分;此响应类型仅允许下载请求,仅IE
支持。
- IE10/IE11 不支持
-
responseText
- 默认值为空字符串
""
- 只有当
responseType
为text
、""
时,xhr
对象上才有此属性,此时才能调用xhr.responseText
,否则抛错。 - 只有当请求成功时,才能拿到正确值。以下
2
种情况下值都为空字符串""
:请求未完成、请求失败。
- 默认值为空字符串
-
responseXML
- 默认值为
null
- 只有当
responseType
为text
、""
、document
时,xhr
对象上才有此属性,此时才能调用xhr.responseXML
,否则抛错。 - 只有当请求成功且返回数据被正确解析时,才能拿到正确值。以下
3
种情况下值都为null
:请求未完成、请求失败、请求成功但返回数据无法被正确解析时。
- 默认值为
-
upload
-
timeout
- 单位毫秒,默认值
0
,即不设置超时。 - 计时从
onloadstart
事件触发开始(即xhr.send()
开始),以onloadend
事件触发为结束。 - 在 IE 中,只能在调用
open()
方法后send()
方法前设置。其他浏览器无此限制,但仍然从xhr.send()
方法调用计时。 - 不能为同步请求设置
timeout
,否则会报错。 - 早期较多浏览器不支持,可通过
setTImeOut
实现。
- 单位毫秒,默认值
-
withCredentials
boolean
类型,默认值false
, 用于跨域请求时将cookie
加入到request header
。xhr.withCredentials
与CORS
什么关系
我们都知道,在发同域请求时,浏览器会将cookie
自动加在request header
中。但在发送跨域请求时,cookie
并不会自动加在request header
中。
造成这个问题的原因:在CORS
标准有如下规定,默认情况下,浏览器在发送跨域请求时,不能发送任何认证信息(credentials
)如cookies
和HTTP authentication schemes
。除非xhr.withCredentials
为true
。cookies
也是一种认证信息,在跨域请求中,client
端必须手动设置xhr.withCredentials=true
,且server
端也必须允许request
能携带认证信息(即response header
中包含Access-Control-Allow-Credentials:true
),这样浏览器才会自动将cookie
加在request header
中。
注意,一旦跨域request
能够携带认证信息,server
端一定不能将Access-Control-Allow-Origin
设置为*,而必须设置为请求页面的域名。
xhr 的事件回调
xhr 共有 8 个事件,分别如下:
onloadstart
onprogress
onabort
ontimeout
onerror
onload
onloadend
onreadystatechange
事件触发条件
引用自 你真的会使用 XMLHttpRequest 吗?
事件 | 触发条件 |
---|---|
onreadystatechange |
每当xhr.readyState 改变时触发;但xhr.readyState 由非 0 值变为 0 时不触发。 |
onloadstart |
调用xhr.send() 方法后立即触发,若xhr.send() 未被调用则不会触发此事件。 |
onprogress |
xhr.upload.onprogress 在上传阶段(即xhr.send() 之后,xhr.readystate=2 之前)触发,每 50ms 触发一次;xhr.onprogress 在下载阶段(即xhr.readystate=3 时)触发,每 50ms 触发一次。 |
onload |
当请求成功完成时触发,此时xhr.readystate=4
|
onloadend |
当请求结束(包括请求成功和请求失败)时触发 |
onabort |
当调用xhr.abort() 后触发 |
ontimeout |
xhr.timeout 不等于 0 ,由请求开始即 onloadstart 开始算起,当到达xhr.timeout 所设置时间请求还未结束即 onloadend ,则触发此事件。 |
onerror |
在请求过程中,若发生 Network error 则会触发此事件(若发生 Network error 时,上传还没有结束,则会先触发 xhr.upload.onerror ,再触发 xhr.onerror ;若发生 Network error 时,上传已经结束,则只会触发xhr.onerror )。注意,只有发生了网络层级别的异常才会触发此事件,对于应用层级别的异常,如响应返回的xhr.statusCode 是 4xx 时,并不属于 Network error ,所以不会触发 onerror 事件,而是会触发 onload 事件。 |
请求正常时,事件触发顺序
- 触发
xhr.onreadystatechange
(之后每次 readyState 变化时,都会触发一次) - 触发
xhr.onloadstart
//上传阶段开始: - 触发
xhr.upload.onloadstart
- 触发
xhr.upload.onprogress
- 触发
xhr.upload.onload
- 触发
xhr.upload.onloadend
//上传结束,下载阶段开始: - 触发
xhr.onprogress
- 触发
xhr.onload
- 触发
xhr.onloadend
发生 abort
/ timeout
/ error
时事件触发顺序
- 触发
xhr.onreadystatechange
事件,此时readystate
为4
-
如果上传阶段还没有结束,则依次触发以下事件:
xhr.upload.onprogress
xhr.upload.[onabort或ontimeout或onerror]
xhr.upload.onloadend
- 触发
xhr.onprogress
事件 - 触发
xhr.[onabort或ontimeout或onerror]
事件 - 触发
xhr.onloadend
事件
事件补充
xhr.upload.onprogress
和 xhr.onprogress
的回调参数为 XMLHttpRequestEventTarget
对象。属性如下:
-
lengthComputable
【只读】,为boolean
值,表示资源是否有可计算的长度。 -
loaded
已接收或已上传的字节数。 -
total
文件总字节数。 -
xhr.upload.onprogress
事件触发于上传阶段,可用于获取上传进度。 -
xhr.onprogress
事件触发于下载阶段,可用于获取下载进度。
后续补充计划
-
fetchAPI
整理。 -
jQuery.ajax
的实现详解。 -
axios
的实现详解。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。